package com.mikufufu.blog.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.mikufufu.blog.common.constant.ContentType;
import com.mikufufu.blog.common.entity.AjaxResult;
import com.mikufufu.blog.common.enums.FriendLinkStatus;
import com.mikufufu.blog.model.entity.LinkExtra;
import com.mikufufu.blog.model.excel.FriendLinkExcel;
import com.mikufufu.blog.model.vo.api.FriendLinkVO;
import com.mikufufu.blog.model.vo.api.LinkExtraVO;
import com.mikufufu.blog.service.LinkExtraService;
import com.mikufufu.blog.utils.BeanUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mikufufu.blog.model.entity.FriendLink;
import com.mikufufu.blog.mapper.FriendLinkMapper;
import com.mikufufu.blog.service.FriendLinkService;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class FriendLinkServiceImpl extends ServiceImpl<FriendLinkMapper, FriendLink> implements FriendLinkService{

    @Autowired
    private LinkExtraService linkExtraService;

    @Override
    public List<FriendLinkVO> getTopLink() {
        List<FriendLink> list = this.list(new LambdaQueryWrapper<FriendLink>()
                .eq(FriendLink::getStatus, FriendLinkStatus.PENDING.getStatus())
                .orderByDesc(FriendLink::getCreateTime)
                .last("limit 4")
        );
        if (list == null || list.isEmpty()){
            return Collections.emptyList();
        }
        // 获取扩展信息
        List<LinkExtra> linkExtras = linkExtraService.list(new LambdaQueryWrapper<LinkExtra>()
                .in(LinkExtra::getLinkId,list.stream().map(FriendLink::getId).collect(Collectors.toList()))
        );
        if (linkExtras == null || linkExtras.isEmpty()){
            return BeanUtil.copyList(list, FriendLinkVO.class);
        }
        // 将扩展信息依据友链的id进行分组
        Map<Integer,List<LinkExtraVO>> map = linkExtras.stream().map(link -> BeanUtil.copy(link, LinkExtraVO.class)).collect(Collectors.groupingBy(LinkExtraVO::getLinkId));
        // 将扩展信息封装到VO中
        List<FriendLinkVO> listVO = BeanUtil.convertList(list, s -> {
            FriendLinkVO friendLinkVO = BeanUtil.copy(s, FriendLinkVO.class);
            friendLinkVO.setExtraVoList(map.get(s.getId()));
            return friendLinkVO;
        });
        return listVO;
    }

    @Override
    public void export(HttpServletResponse response) {
        // 这里注意 有同学反应使用swagger 会导致各种问题，请直接用浏览器或者用postman
        try {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("友链列表", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");


            List<FriendLinkExcel> list = this.list().stream().map(friendLink -> BeanUtil.copy(friendLink, FriendLinkExcel.class)).collect(Collectors.toList());

            // 这里需要设置不关闭流
            EasyExcel.write(response.getOutputStream(), FriendLinkExcel.class)
                    .autoCloseStream(Boolean.FALSE)
                    .sheet("友链信息")
                    .doWrite(list);

        } catch (Exception e) {
            log.error("下载文件失败 {}", e.getMessage(),e);
            // 重置response
            response.reset();
            response.setContentType(ContentType.JSON);
            response.setCharacterEncoding("utf-8");
            try {
                response.getWriter().println(JSON.toJSONString(AjaxResult.error("下载文件失败："+e.getMessage())));
            }catch (IOException io){
                log.error("下载文件失败",io);
            }
        }
    }
}
